/*
* EP-Tracing System : a tool to trace mountain hike.           .kNNx
* Copyright (C) 2009  Raffaello Brondi                         'KNNNk
*                                                             ,XNNNl
* This program is free software:                             ,XNN0'
* you can redistribute it and/or modify                     ,XNNx.
* it under the terms of the                                'XNNl
* GNU General Public License                              .KNN:                     ..
* as published by                                        .0NNo                    .ONNO.
* the Free Software Foundation,                          xNNN.  :dkd,            .KNNNN;
* either version 3 of the License, or                   :NNNK ;XNNNNNo          ,KNNNX:
* (at your option) any later version.                   xNNNNcXNNNNNNk         cNNNNx.
*                                                       ,XNNNNNNNNNNX'       .xNNNK;
*                                                        .lKNNNNNNNK'       :KNNNo
*                                                          ;kNNNNNKxl;'.'l0NNNk.
* This program is distributed in                          .'  .:xXNNNNNNNNNNNO,
* the hope that it will be useful,                       :NNXd'   ,oONNNNNNk,
* but WITHOUT ANY WARRANTY;                              xNNNNN0c.    .;;,.
* without even the implied warranty of                   kNNNNNNNXd'
* MERCHANTABILITY or                                     xNNNNNNNNNNOc.
* FITNESS FOR A PARTICULAR PURPOSE.                      xNNNNNNNNNNNNXd.
* See the GNU General Public License                     ONNNN0.,o0NNNNNNl
* for more details.                                      0NNNNd    kNNNNNX.
*                                                        KNNNNl   oNNNNNXc
*                                                       .XNNNN:  dNNNNNx.
* You should have received a copy                       .XNNNN; lNNNNO'
* of the GNU General Public License                     .XNNNN; 'dxo'
* along with this program.                              .XNNNN;
* If not, see <http://www.gnu.org/licenses/>.            0NNNN:
*                                                        kNNNNc
*                                                        oNNNNd
*                                                        ;NNNN0
* Contact: rbrondi@gmail.com                             .XNNNN;
*                                                         kNNNNd
*                                                         .coo:.
*/

package EP.UI.Trace;

import EP.GPS.Path.PathPoint;
import EP.GPS.Path.SwappablePathBuffer;
import EP.Utils;
import java.io.IOException;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;

import javax.microedition.lcdui.Image;
import javax.microedition.location.LocationProvider;
import javax.microedition.location.QualifiedCoordinates;

/**
 * Viewer class that renders current location updates.
 */
public class TracerState extends Canvas implements GPSUI {

    private final byte GREEN = 0;
    private final byte ORANGE = 1;
    private final byte RED = 2;
    private final String title = "Recording your hike";
    private TripSetup trip;
    private String TracerState;
    //private StringBuffer points;
    private SwappablePathBuffer buffer;
    private QualifiedCoordinates coord;
    private Image gpsStatus;
    private byte statusSelected;
    private Chronometer cron;
    private String cronTime;
    private float distance;
    /** Save hike */
    private Command saveCmd = new Command("Save hike", Command.OK, 1);
    /** Abort hike recording*/
    private Command abortCmd = new Command("Abort", Command.STOP, 1);

    public TracerState(TripSetup t, CommandListener cmdListener) {
        this.trip = t;
        addCommand(this.abortCmd);
        addCommand(this.saveCmd);
        setCommandListener(cmdListener);

        this.TracerState = "Unknown";
        try {
            this.gpsStatus = Image.createImage("/orange_light.png");
        } catch (IOException ex) {
            ex.printStackTrace();
            this.gpsStatus = null;
        }
        this.statusSelected = this.ORANGE;

        this.cron = new Chronometer(this);
        this.cron.start();

        this.coord = null;
        this.distance = 0;

        //this.points = new StringBuffer();
        this.buffer = new SwappablePathBuffer(30);
    }

    public void setTracerState(int state) {
        switch (state) {
            case LocationProvider.AVAILABLE:
                this.TracerState = "Available";
                if (this.statusSelected != this.GREEN) {
                    try {
                        this.gpsStatus = Image.createImage("/green_light.png");
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        this.gpsStatus = null;
                    }
                }
                this.statusSelected = this.GREEN;
                //this.locP.setLocationListener(this, -1, 0, 0);
                break;
            case LocationProvider.OUT_OF_SERVICE:
                this.TracerState = "Out of Service";
                if (this.statusSelected != this.RED) {
                    try {
                        this.gpsStatus = Image.createImage("/red_light.png");
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        this.gpsStatus = null;
                    }
                }
                this.statusSelected = this.RED;
                //this.locP.setLocationListener(null, -1, 0, 0);
                break;
            case LocationProvider.TEMPORARILY_UNAVAILABLE:
                this.TracerState = "Temporarily unavailable";
                if (this.statusSelected != this.ORANGE) {
                    try {
                        this.gpsStatus = Image.createImage("/orange_light.png");
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        this.gpsStatus = null;
                    }
                }
                //this.locP.setLocationListener(null, -1, 0, 0);
                this.statusSelected = this.ORANGE;
                break;
            default:
                this.TracerState = "Temporarily unavailable";
                if (this.statusSelected != this.ORANGE) {
                    try {
                        this.gpsStatus = Image.createImage("/orange_light.png");
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        this.gpsStatus = null;
                    }
                }
                this.statusSelected = this.ORANGE;
                //this.locP.setLocationListener(null, -1, 0, 0);
                break;
        }
        this.repaint();
    }

    public void setCoord(QualifiedCoordinates coord) {
        PathPoint p;
        if (this.trip.getAltitude()) {
            p = new PathPoint(coord.getLatitude(), coord.getLongitude(), coord.getAltitude());

        } else {
            p = new PathPoint(coord.getLatitude(), coord.getLongitude());
        }

        if(p.equals(this.buffer.getLast()))
            return;

        if (this.coord != null) {
            this.distance += (this.coord.distance(coord) / 1000);
        }

        this.coord = coord;
        this.buffer.put(p);
    }

    protected void paint(Graphics g) {
        Font f = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
        g.setFont(f);

        // use font height as a line height
        int lineHeight = f.getHeight();
        // current line counter
        int line = 0;

        // clean the backround
        g.setColor(0xaaaaaa);
        g.fillRect(0, 0, getWidth(), getHeight());

        g.setColor(0x000000);

        g.drawString(this.title, 0, lineHeight * (line++), Graphics.LEFT | Graphics.TOP);
        line++;

        int imageWidth = 0;
        if (this.gpsStatus != null) {
            g.drawImage(this.gpsStatus, 0, lineHeight * (line), Graphics.LEFT | Graphics.TOP);
            imageWidth = this.gpsStatus.getWidth();
        }

        g.drawString(this.TracerState, imageWidth, lineHeight * (line++), Graphics.LEFT | Graphics.TOP);
        if (coord != null) {
            line++;

            double lat = coord.getLatitude();
            double lon = coord.getLongitude();

            g.drawString("Lat : " + Utils.formatDouble(lat, 4), 0, lineHeight * (line++), Graphics.TOP | Graphics.LEFT);
            g.drawString("Lon: " + Utils.formatDouble(lon, 4), 0, lineHeight * (line++), Graphics.TOP | Graphics.LEFT);

            if (this.trip.getAltitude()) {
                double altitude = coord.getAltitude();
                g.drawString("Altitude : " + Utils.formatDouble(altitude, 3), 0, lineHeight * (line++), Graphics.TOP | Graphics.LEFT);
            }
        }

        line += 2;
        g.drawString("Total distance : " + Utils.formatDouble(this.distance, 3) + " km", this.getWidth() / 2, lineHeight * (line++), Graphics.HCENTER | Graphics.BASELINE);

        line += 2;
        g.drawString("Elapsed time " + this.cronTime, this.getWidth() / 2, lineHeight * (line++), Graphics.HCENTER | Graphics.BASELINE);

    }

    public Command getSaveCommand() {
        return this.saveCmd;
    }

    public Command getAbortCommand() {
        return this.abortCmd;
    }

    /*public String getPoints() {
        StringBuffer str = new StringBuffer();
        str.append("\n{\"trp\":\"" + this.trip.getTripName());

        str.append("\",\"tt\":\"" + this.cronTime + "\"");
        str.append(",\"td\":\"" + this.distance + "\"");

        //str.append(",\"ps\":[" + this.points + "]}");

        return str.toString();
    }*/

    public void closeTrip() {
        StringBuffer str = new StringBuffer();
        str.append("],\"" + Utils.HIKE_NAME + "\":\"" + this.trip.getTripName());

        str.append("\",\"" + Utils.HIKE_ALTITUDE + "\":\"" + String.valueOf(this.trip.getAltitude()));
        str.append("\",\"" + Utils.HIKE_TOTAL_TIME + "\":\"" + this.cronTime + "\"");
        str.append(",\"" + Utils.HIKE_TOTAL_DISTANCE + "\":\"" + this.distance + "\"}");
        this.buffer.flush(str.toString());
    }

    public void setChronometerTime(String time) {
        this.cronTime = time;
        this.repaint();
    }
}
